<template>
  <div class="vr-container">
    <div ref="container" class="vr-canvas-container"></div>
        <div class="vr-controls">
          <button @click="switchTexture(0)">正面</button>
          <button @click="switchTexture(1)">大门</button>
          <button @click="switchTexture(2)">背面</button>
        </div>
  </div>
</template>

<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

export default {
  name: 'VRViewer',
  props: {
    images: {
      type: Array,
      required: true,
      validator: value => value.length > 0
    }
  },
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      controls: null,
      sphere: null,
      animationFrameId: null,
      textures: [],
      currentTextureIndex: 0,
      texturesLoaded: false,
      loadedTexturesCount: 0,
    };
  },
  mounted() {
    this.initThree()
    this.loadVRTextures()
    window.addEventListener('resize', this.handleResize)
    // 防止拖拽时选中文字
    document.onselectstart = () => false;
    // 防止右键菜单
    this.renderer.domElement.oncontextmenu = () => false;
  },
  activated() {
    this.reactivate();
  },
  deactivated(){
    this.partialCleanup()
  },
  beforeDestroy() {
     this.fullCleanup();
  },
  methods: {
    fullCleanup() {
      this.partialCleanup(); // 先执行部分清理

      // 释放渲染器、场景、相机等核心对象
      if (this.renderer) {
        this.renderer.dispose();
        this.renderer.domElement.removeEventListener('dblclick', this.resetView);
        if (this.$refs.container?.contains(this.renderer.domElement)) {
          this.$refs.container.removeChild(this.renderer.domElement);
        }
        this.renderer = null;
      }

      if (this.scene) {
        this.scene.traverse(obj => {
          if (obj.geometry) obj.geometry.dispose();
          if (obj.material) {
            obj.material.dispose();
            if (obj.material.map) obj.material.map.dispose();
          }
        });
        this.scene = null;
      }

      if (this.camera) {
        this.camera = null;
      }

      // 恢复文档默认行为
      document.onselectstart = null;
    },
    partialCleanup() {
      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId);
        this.animationFrameId = null;
      }

      if (this.controls) {
        this.controls.dispose();
        this.controls = null;
      }

      if (this.sphere) {
        if (this.sphere.geometry) this.sphere.geometry.dispose();
        if (this.sphere.material) {
          this.sphere.material.dispose();
          if (this.sphere.material.map) this.sphere.material.map.dispose();
        }
        this.scene.remove(this.sphere);
        this.sphere = null;
      }

      this.textures.forEach(texture => texture && texture.dispose());
      this.textures = [];
      this.loadedTexturesCount = 0;
      this.texturesLoaded = false;
    },
    reactivate() {
      if (!this.$refs.container) return;
      
      // 重新添加DOM元素
      if (this.renderer && !this.$refs.container.contains(this.renderer.domElement)) {
        this.$refs.container.appendChild(this.renderer.domElement);
      }

      // 重新初始化必要的部分
      if (!this.controls) {
        this.initOrbitControls();
      }

      // 重新加载纹理（如果已加载则直接使用）
      if (this.textures.length === 0) {
        this.loadVRTextures();
      } else if (this.texturesLoaded) {
        this.createVRSpere(this.textures[this.currentTextureIndex]);
        this.animate();
      }
    },

    initThree() {
      // 1. 创建场景
      this.scene = new THREE.Scene()

      // 2. 创建相机
      this.camera = new THREE.PerspectiveCamera(
        75,
        this.$refs.container.clientWidth / this.$refs.container.clientHeight,
        0.1,
        1000
      )
      this.camera.position.z = 0.1

      // 3. 创建渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true })
      this.renderer.setSize(
        this.$refs.container.clientWidth,
        this.$refs.container.clientHeight
      )
      this.$refs.container.appendChild(this.renderer.domElement)
      this.renderer.domElement.addEventListener('dblclick', this.resetView)
      // 4. 初始化轨道控制器
      this.initOrbitControls()
    },
    initOrbitControls() {
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
      
      // 优化控制参数
      this.controls.enableDamping = true      // 启用阻尼效果
      this.controls.dampingFactor = 0.05     // 阻尼惯性系数
      this.controls.rotateSpeed = 0.25       // 降低旋转速度
      this.controls.zoomSpeed = 0.8          // 缩放速度
      this.controls.panSpeed = 0.8           // 平移速度
      
      // 限制垂直旋转角度，防止天旋地转
      this.controls.minPolarAngle = Math.PI / 6  // 最小角度(30度)
      this.controls.maxPolarAngle = Math.PI * 5/6 // 最大角度(150度)
      
      // 禁用缩放和平移
      this.controls.enableZoom = false
      this.controls.enablePan = false
    },
    loadVRTextures() {
      const textureLoader = new THREE.TextureLoader()
      const texturePaths = this.images
      
      this.textures = texturePaths.map(path => {
        const texture = textureLoader.load(
          path,
          () => this.onTextureLoaded(), // 加载完成回调
          undefined, // 进度回调
          (err) => console.error('加载纹理出错:', err) // 错误回调
        )
        return texture
      })
    },
    onTextureLoaded() {
      this.loadedTexturesCount++
      // 当所有纹理都加载完成
      if (this.loadedTexturesCount === this.textures.length) {
        this.texturesLoaded = true
        this.createVRSpere(this.textures[0])
        this.animate()
      }
    },
    createVRSpere(texture) {
      // 如果已有球体，先移除
      if (this.sphere) {
        this.scene.remove(this.sphere)
      }
      
      // 创建球体作为VR全景容器
      const geometry = new THREE.SphereGeometry(500, 60, 40)
      // 将球体内外翻转，使纹理显示在内侧
      geometry.scale(-1, 1, 1)
      
      const material = new THREE.MeshBasicMaterial({
        map: texture
      })
      
      this.sphere = new THREE.Mesh(geometry, material)
      this.scene.add(this.sphere)
    },

    animate() {
      this.animationFrameId = requestAnimationFrame(this.animate)
      // 更新控制器
      this.controls.update()
      this.renderer.render(this.scene, this.camera)
    },

    handleResize() {
      this.camera.aspect = this.$refs.container.clientWidth / this.$refs.container.clientHeight
      this.camera.updateProjectionMatrix()
      this.renderer.setSize(
        this.$refs.container.clientWidth,
        this.$refs.container.clientHeight
      )
    },
    switchTexture(index) {
      this.currentTextureIndex = index
        // 切换到下一张图片
        this.sphere.material.map = this.textures[index]
        this.sphere.material.needsUpdate = true
        this.controls.reset()
        // 获取当前水平角度
        const currentAzimuth = Math.atan2(
          this.controls.target.z - this.camera.position.z,
          this.controls.target.x - this.camera.position.x
        );
        // 获取当前垂直角度
        const currentPolar = Math.asin(
          (this.controls.target.y - this.camera.position.y) / 
          this.camera.position.distanceTo(this.controls.target)
        );
        const radius = 5; // 控制旋转半径
       
        if (index === 1) {
          const newAngle = currentAzimuth - (80 * Math.PI / 180);
          const newPolar = currentPolar + (-30 * Math.PI / 180);
           // 计算新的目标位置
          this.controls.target.set(
            this.camera.position.x + radius * Math.cos(newAngle),
            this.controls.target.y + radius * Math.sin(newPolar),
            this.camera.position.z + radius * Math.sin(newAngle)
          );
        }

        if (index === 2) {
          const newAngle = currentAzimuth - (140 * Math.PI / 180);
          const newPolar = currentPolar + (-30 * Math.PI / 180);
          this.controls.target.set(
            this.camera.position.x + radius * Math.cos(newAngle),
            this.controls.target.y + radius * Math.sin(newPolar),
            this.camera.position.z + radius * Math.sin(newAngle)
          );
        }

        // 强制更新控制器
        this.controls.update();
    },
    resetView(){
      this.switchTexture(this.currentTextureIndex)
    }
  }
};
</script>

<style scoped>
.vr-container {
  position: relative;
  width: 100%;
  height: 100%;
}

.vr-canvas-container {
  width: 100%;
  height: 100%;
}

.vr-controls {
  position: absolute;
  bottom: 20px;
  width: 100%;
  text-align: center;
  color: white;
  z-index: 100;
}

.vr-controls button {
  background: rgba(0, 0, 0, 0.5);
  color: white;
  border: none;
  padding: 8px 16px;
  margin: 0 10px;
  border-radius: 4px;
  cursor: pointer;
}

.vr-controls button:hover {
  background: rgba(0, 0, 0, 0.7);
}
</style>